/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.taglib.core.content.editor;

import com.blandware.atleap.common.util.StringUtil;
import com.blandware.atleap.webapp.util.core.*;
import org.apache.commons.validator.GenericValidator;
import org.apache.struts.taglib.TagUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * <p>Renders WYSIWYG editor, currently FCKEditor or TinyMCE. That editor
 * is assigned to be used to edit content of some field with complex formatting
 * which is represented with HTML.
 * </p>
 * <p>
 * Allowed attributes are:
 * <ul>
 * <li>
 * <b>type</b> - "FCKEditor" or "TinyMCE". If not specified, or specified value
 * is not one of these two values, then value of global property is checked.
 * If it's still not one of them, "TinyMCE" is used.
 * </li>
 * <li>
 * <b>id</b> - unique id of rendered editor
 * </li>
 * <li>
 * <b>basePath</b> - directory where the FCKeditor files reside on the server
 * (only for FCKEditor)
 * </li>
 * <li>
 * <b>baseHref</b> - base HREF (value of attribute <code>href</code> of
 * <code>base</code> tag in editor window)
 * </li>
 * <li>
 * <b>defaultLanguage</b> - language to use to render editor (for localized
 * interface and so on). For example, "en".
 * </li>
 * <li>
 * <b>editorAreaLanguage</b> - language of currently rendered editor window.
 * This language will be sent to link or image browser.
 * </li>
 * <li>
 * <b>fullPage</b> - whether or not to render full page in editor window (with
 * <code>html</code>, <code>head</code> and <code>body</code> tags)
 * </li>
 * <li>
 * <b>editorAreaCss</b> - path to CSS-file to use in editor window. You may use
 * reserved word 'no_stylesheet' to say that no CSS file must be used in editor
 * window.
 * </li>
 * <li>
 * <b>width</b> - width of editor window
 * </li>
 * <li>
 * <b>height</b> - height of editor window
 * </li>
 * </ul>
 * </p>
 * <p><a href="ContentEditorTag.java.html"><i>View Source</i></a></p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.23 $ $Date: 2008/03/19 15:16:44 $
 * @jsp.tag name="contentEditor"
 * body-content="scriptless"
 */
public class ContentEditorTag extends SimpleTagSupport {

	// ~ Static fields/initializers

	/**
	 * TinyMCE editor (<a href="http://tinymce.moxiecode.com/">http://tinymce.moxiecode.com/</a>)
	 */
	public static final String EDITOR_TYPE_TINYMCE = "TinyMCE";

	/**
	 * FCKEditor (<a href="http://fckeditor.net">http://fckeditor.net</a>)
	 */
	public static final String EDITOR_TYPE_FCKEDITOR = "FCKEditor";

	/**
	 * Keyword to determine that no CSS file must be used for content in editor window
	 */
	public static final String EDITOR_AREA_CSS_NO_STYLESHEET = "no_stylesheet";

	/**
	 * Context key under which count of already rendered TinyMCE editors is stored
	 */
	public static final String TINY_MCE_COUNT_KEY = "com.blandware.atleap.webapp.taglib.core.content.editor.TINY_MCE_COUNT";

	/**
	 * Context key under which count of already rendered FCK editors is stored
	 */
	public static final String FCKEDITOR_COUNT_KEY = "com.blandware.atleap.webapp.taglib.core.content.editor.FCKEDITOR_COUNT";

	/**
	 * Count of already rendered TinyMCE editors for internal use
	 */
	protected int tinyMCECount = 0;

	/**
	 * Type of editor to render
	 */
	protected String type = null;

	// ~ Instance variables

	/**
	 * Unique ID of this editor
	 */
	protected String id;

	/**
	 * Dir where the FCKeditor files reside on the server
	 */
	protected String basePath = null;

	/**
	 * Language to use to render editor
	 */
	protected String defaultLanguage;

	/**
	 * Base HREF (value of attribute <code>href</code> of <code>base</code> tag in editor window)
	 */
	protected String baseHref;

	/**
	 * Language of currently rendered editor window. This language will be sent to link or image browser
	 */
	protected String editorAreaLanguage;

	/**
	 * Whether or not to render full page in editor window (with <code>html</code>, <code>head</code> and <code>body</code> tags)
	 */
	protected Boolean fullPage;

	/**
	 * Path to CSS-file to use in editor window. You may use reserved word 'no_stylesheet' to say that no CSS file must be used
	 * in editor window
	 */
	protected String editorAreaCss;

	/**
	 * Width of editor window
	 */
	protected String width = null;

	/**
	 * Height of editor window
	 */
	protected String height = null;

	/**
     * Returns editor type
     *
     * @return editor type
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Type of editor to render"
	 */
	public String getType() {
		return type;
	}

    /**
     * Sets editor type
     *
     * @param type editor type to set
     */
	public void setType(String type) {
		this.type = type;
	}


	/**
	 * Gets the unique id of the editor
	 *
	 * @return id
	 * @jsp.attribute required="true"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Unique id of the editor"
	 */
	public String getId() {
		return id;
	}

	/**
	 * Sets the unique id of the editor
	 *
	 * @param value name
	 */
	public void setId(String value) {
		id = value;
	}

	/**
	 * Gets the dir where the FCKeditor files reside on the server
	 *
	 * @return path
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Dir where the FCKeditor files reside on the server"
	 */
	public String getBasePath() {
		return basePath;
	}

	/**
	 * Sets the dir where the FCKeditor files reside on the server
	 *
	 * @param value path
	 */
	public void setBasePath(String value) {
		basePath = value;
	}

	/**
     * Returns default language
     *
     * @return default language
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Language to use to render editor"
	 */
	public String getDefaultLanguage() {
		return defaultLanguage;
	}

    /**
     * Sets default language
     *
     * @param defaultLanguage default language to set
     */
	public void setDefaultLanguage(String defaultLanguage) {
		this.defaultLanguage = defaultLanguage;
	}

	/**
     * Returns base href
     *
     * @return base href
     * @see #baseHref
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Base HREF (value of attribute 'href' of 'base' tag in editor window)"
	 */
	public String getBaseHref() {
		return baseHref;
	}

    /**
     * Sets base href
     *
     * @param baseHref base href to set
     * @see #baseHref
     */
	public void setBaseHref(String baseHref) {
		this.baseHref = baseHref;
	}

	/**
     * Returns editor area language
     *
     * @return editor area language
     * @see #editorAreaLanguage
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Language of currently rendered editor window. THis language will be sent to link or image browser"
	 */
	public String getEditorAreaLanguage() {
		return editorAreaLanguage;
	}

    /**
     * Sets editor area language
     *
     * @param editorAreaLanguage editor area language to set
     * @see #editorAreaLanguage
     */
	public void setEditorAreaLanguage(String editorAreaLanguage) {
		this.editorAreaLanguage = editorAreaLanguage;
	}

	/**
     * Returns whether or not to render full page in editor window
     *
     * @return whether or not to render full page in editor window
     * @see #fullPage
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.Boolean"
	 * description="Whether or not to render full page in editor wndow"
	 */
	public Boolean getFullPage() {
		return fullPage;
	}

    /**
     * Sets whether or not to render full page in editor window
     *
     * @param fullPage whether or not to render full page in editor window
     * @see #fullPage
     */
	public void setFullPage(Boolean fullPage) {
		this.fullPage = fullPage;
	}

	/**
     * Returns editor area CSS
     *
     * @return editor area CSS
     * @see #editorAreaCss
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Path to CSS-file to use in editor window"
	 */
	public String getEditorAreaCss() {
		return editorAreaCss;
	}

    /**
     * Sets editor area CSS
     *
     * @param editorAreaCss editor area CSS to set
     * @see #editorAreaCss
     */
	public void setEditorAreaCss(String editorAreaCss) {
		this.editorAreaCss = editorAreaCss;
	}

	/**
	 * Gets the width of the textarea
	 *
	 * @return width
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Width of the textarea"
	 */
	public String getWidth() {
		return width;
	}

	/**
	 * Sets the width of the textarea
	 *
	 * @param value width
	 */
	public void setWidth(String value) {
		width = value;
	}

	/**
	 * Gets the height of the textarea
	 *
	 * @return height
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Height of the textarea"
	 */
	public String getHeight() {
		return height;
	}

	/**
	 * Sets the height of the textarea
	 *
	 * @param value height
	 */
	public void setHeight(String value) {
		height = value;
	}

	/**
	 * Initializes the editor container and sets attributes
	 */
	public void doTag() throws JspException, IOException {

		PageContext pageContext = (PageContext) getJspContext();
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
        ServletContext servletContext = pageContext.getServletContext();
        GlobalProperties globalProperties = GlobalProperties.getInstance(servletContext);

        if ( !EDITOR_TYPE_FCKEDITOR.equalsIgnoreCase(type) && !EDITOR_TYPE_TINYMCE.equalsIgnoreCase(type) ) {
			// get global property value
            type = globalProperties.getString(WebappConstants.GLOBAL_PROPERTY_WYSIWYG_EDITOR_TYPE, EDITOR_TYPE_TINYMCE);
			if ( !EDITOR_TYPE_FCKEDITOR.equalsIgnoreCase(type) && !EDITOR_TYPE_TINYMCE.equalsIgnoreCase(type) ) {
				// default is TinyMCE
				type = EDITOR_TYPE_TINYMCE;
			}
		}

		// calculate counts
		if ( EDITOR_TYPE_FCKEDITOR.equalsIgnoreCase(type) ) {
			Integer tagNumber = (Integer) pageContext.getAttribute(FCKEDITOR_COUNT_KEY, PageContext.REQUEST_SCOPE);
			if ( tagNumber == null ) {
				tagNumber = new Integer(0);
			} else {
				tagNumber = new Integer(tagNumber.intValue() + 1);
			}
			pageContext.setAttribute(FCKEDITOR_COUNT_KEY, tagNumber, PageContext.REQUEST_SCOPE);
		} else {
			Integer tagNumber = (Integer) pageContext.getAttribute(TINY_MCE_COUNT_KEY, PageContext.REQUEST_SCOPE);
			if ( tagNumber == null ) {
				tagNumber = new Integer(0);
			} else {
				tagNumber = new Integer(tagNumber.intValue() + 1);
			}
			pageContext.setAttribute(TINY_MCE_COUNT_KEY, tagNumber, PageContext.REQUEST_SCOPE);
			this.tinyMCECount = tagNumber.intValue();
		}

		// base path is used by FCKEditor only
		if ( basePath == null ) {
			basePath = ((HttpServletRequest) pageContext.getRequest()).getContextPath() + "/FCKeditor/";
		}

		// ensure, that default language is set
		if ( GenericValidator.isBlankOrNull(defaultLanguage) ) {
			Locale locale = WebappUtil.getEnsuredUserLocale(request);
			if ( locale == null ) {
				defaultLanguage = LocaleUtil.getInstance(servletContext).getDefaultLocale().getIdentifier();
			} else {
				defaultLanguage = locale.getLanguage();
			}
		}

		// ensure that content css is set
		if ( editorAreaCss == null ) {
            // nothing supplied, try to use default value
            String defaultCss = globalProperties.getString(WebappConstants.GLOBAL_PROPERTY_DEFAULT_CONTENT_EDITOR_CSS);
            if (!GenericValidator.isBlankOrNull(defaultCss)) {
                editorAreaCss = request.getContextPath() + defaultCss;
            } else {
                String adminTheme = globalProperties.getString(WebappConstants.GLOBAL_PROPERTY_ADMIN_CSS_THEME);
                editorAreaCss = request.getContextPath() + "/styles/theme/" + adminTheme + "/theme.css";
            }
		} else if ( EDITOR_AREA_CSS_NO_STYLESHEET.equalsIgnoreCase(editorAreaCss) ) {
			editorAreaCss = "";
		}

		// set default width
		if ( GenericValidator.isBlankOrNull(width) ) {
			width = "100%";
		}

		// set default height
		if ( GenericValidator.isBlankOrNull(height) ) {
			height = "400px;";
		}

		StringWriter sw = new StringWriter();
		getJspBody().invoke(sw);
		String htmlCode;
		if ( EDITOR_TYPE_FCKEDITOR.equalsIgnoreCase(type) ) {
			htmlCode = createFCKEditorHTML(sw.toString());
		} else {
			htmlCode = createTinyMCEHTML(sw.toString());
		}
		TagUtils.getInstance().write(pageContext, htmlCode);
	}

	/**
	 * Returns <code>true</code> if editor is compatible with used user agent
	 *
	 * @return <code>true</code> if editor is compatible with used user agent
	 */
	protected boolean isCompatible() {

		PageContext pageContext = (PageContext) getJspContext();
		String userAgent = ((HttpServletRequest) pageContext.getRequest()).getHeader("user-agent");
		if ( userAgent == null ) {
			return false;
		} else {
			userAgent = userAgent.toLowerCase();
		}

		boolean compatible = false;

		// check according to type
		if ( EDITOR_TYPE_FCKEDITOR.equalsIgnoreCase(type) ) {
			if ((userAgent.indexOf("safari") != -1)) {
				if ( retrieveBrowserVersion(userAgent) >= 3.0 ) {
					compatible = true;
				}
            } else if ((userAgent.indexOf("opera") != -1)) {
				if ( retrieveBrowserVersion(userAgent) >= 9.5 ) {
					compatible = true;
				}
            } else if ( (userAgent.indexOf("msie") != -1) && (userAgent.indexOf("mac") == -1) && (userAgent.indexOf("opera") == -1) ) {
				if ( retrieveBrowserVersion(userAgent) >= 5.5 ) {
					compatible = true;
				}
			} else if ( userAgent.indexOf("gecko") != -1 ) {
				if ( retrieveBrowserVersion(userAgent) >= 20030210 ) {
					compatible = true;
				}
			}
		} else {
			if ( userAgent.indexOf("opera") != -1 ) {
				compatible = false;
			} else if ( userAgent.indexOf("msie") != -1 ) {
				if ( retrieveBrowserVersion(userAgent) >= 5.5 ) {
					compatible = true;
				}
			} else if ( userAgent.indexOf("gecko") != -1 ) {
				// todo: check version (what is the correct version)
				compatible = true;
			} else if ( userAgent.indexOf("mac") != -1 ) {
				compatible = true;
			} else {
				compatible = false;
			}
		}

		return compatible;
	}

	/**
	 * Retrieves browser version
	 *
	 * @param userAgent UserAgent string
	 * @return Browser version
	 */
	protected double retrieveBrowserVersion(String userAgent) {
		if ( userAgent.indexOf("safari") > -1 ) {
			String str = userAgent.substring(0, userAgent.indexOf("safari"));
            str = str.substring(str.lastIndexOf('/') + 1);
            return Double.parseDouble(str.trim());
		} else if ( userAgent.indexOf("opera") > -1 ) {
			String str = userAgent.substring(userAgent.indexOf("opera") + 6);
			return Double.parseDouble(str.substring(0, str.indexOf(" ")));
		} else if ( userAgent.indexOf("msie") > -1 ) {
			String str = userAgent.substring(userAgent.indexOf("msie") + 5);
			return Double.parseDouble(str.substring(0, str.indexOf(";")));
		} else {
			String str = userAgent.substring(userAgent.indexOf("gecko") + 6);
			return Double.parseDouble(str.substring(0, 8));
		}
	}


	/**
	 * Generates the HTML Code for the FCK editor.
	 * <br />
	 * Evalutes the browser capabilities and generates the editor if browser is
     * IE 5.5, Gecko 20030210, Opera 9.5 or greater, or a simple textarea
     * otherwise.
	 *
	 * @param content Content of the editor window
	 * @return HTML code representing editor window
	 */
	protected String createFCKEditorHTML(String content) {
		StringBuffer strEditor = new StringBuffer();

		strEditor.append("<div>");
		content = StringUtil.htmlEncode(content);

		if ( isCompatible() ) {

			if ( content != null && content.trim().length() > 0 ) {
                strEditor.append("<input type=\"hidden\" id=\"").append(id).append("\" name=\"").append(id).append("\" value=\"").append(content).append("\">");
			} else {
                strEditor.append("<input type=\"hidden\" id=\"").append(id).append("\" name=\"").append(id).append("\">");
			}

			strEditor.append(createFCKConfigHTML());
			strEditor.append(createFCKIFrameHTML());

		} else {
            strEditor.append("<textarea name=\"").append(id).append("\" rows=\"4\" cols=\"40\" style=\"width: ").append(width).append("; height: ").append(height).append("\" wrap=\"virtual\">").append(content).append("</textarea>");
		}
		strEditor.append("</div>");
		return strEditor.toString();
	}

	/**
	 * Collects all values and puts 'em into string. Creates <code>hidden</code> element which stores string.
	 *
	 * @return String representing HTML <code>hidden</code> element which stores configuration
	 */
	protected String createFCKConfigHTML() {

		// create config map
		Map config = new HashMap();
		config.put("DefaultLanguage", defaultLanguage);
		config.put("BaseHref", baseHref);
		config.put("EditorAreaLanguage", editorAreaLanguage);
		config.put("FullPage", fullPage);
		config.put("EditorAreaCSS", editorAreaCss);

		// create query string
		String configStr = RequestUtil.createQueryStringFromMap(config, "&").toString();

		return "<input type=\"hidden\" id=\"" + id + "___Config\" value=\"" + configStr + "\">";
	}

	/**
	 * Creates <code>iframe</code> element which is used to render editor window
	 *
	 * @return String representing <code>iframe</code> element used to render editor window
	 */
	protected String createFCKIFrameHTML() {

		String src = basePath + "editor/fckeditor.html?InstanceName=" + id;
		src += "&Toolbar=Default";

		StringBuffer iframe = new StringBuffer("<iframe");
		iframe.append(" src=\"").append(src).append("\"");
		iframe.append(" id=\"").append(id).append("\"");
		iframe.append(" name=\"").append(id).append("\"");
		StringBuffer style = new StringBuffer();
		if ( !GenericValidator.isBlankOrNull(width) ) {
			style.append(" width: ").append(width).append(";");
		}
		if ( !GenericValidator.isBlankOrNull(height) ) {
			style.append(" height: ").append(height).append(";");
		}
		if ( style.length() > 0 ) {
			iframe.append(" style=\"").append(style).append("\"");
		}
		iframe.append(" frameborder=\"no\"");
		iframe.append(" scrolling=\"no\"");
		iframe.append(">");
		iframe.append("</iframe>");
		return iframe.toString();

	}

	/**
	 * Creates TinyMCE editor window
	 *
	 * @param content Content of the editor window
	 * @return HTML code representing the editor window
	 */
	protected String createTinyMCEHTML(String content) {
		StringBuffer htmlCode = new StringBuffer();
		if ( tinyMCECount == 0 ) {
			htmlCode.append(createTinyMCEInitCode()).append("\n");
		}

		// add editor area language, if specified
		StringBuffer languageScript = new StringBuffer("<script language=\"javascript\">");
		languageScript.append("this.editorAreaLanguages[\"")
                .append(id.replace('"', '_')).append("\"] = ");
		if ( !GenericValidator.isBlankOrNull(editorAreaLanguage) ) {
			languageScript.append("\"").append(editorAreaLanguage).append("\"");
		} else {
			languageScript.append("null");
		}
		languageScript.append(";");
		languageScript.append("</script>");

		// insert textarea element
		StringBuffer editor = new StringBuffer("<textarea");
		editor.append(" id=\"").append(id).append("\"");
		editor.append(" name=\"").append(id).append("\"");

		StringBuffer style = new StringBuffer();
		if ( !GenericValidator.isBlankOrNull(width) ) {
			style.append(" width: ").append(width).append(";");
		}
		if ( !GenericValidator.isBlankOrNull(height) ) {
			style.append(" height: ").append(height).append(";");
		}
		if ( style.length() > 0 ) {
			editor.append(" style=\"").append(style).append("\"");
		}
		editor.append(" class=\"contentEditorInstance\"");
		editor.append(">");

		// append content
		if ( content != null ) {
			editor.append(content).append("\n");
		}

		// close textearea element
		editor.append("</textarea>");

		htmlCode.append(languageScript);
		htmlCode.append(editor);

		return htmlCode.toString();
	}

	/**
	 * Creates initialization code for TinyMCE
	 *
	 * @return String representing init code for Tiny MCE
	 */
	protected StringBuffer createTinyMCEInitCode() {
        PageContext pageContext = (PageContext) getJspContext();
        HttpServletRequest request
                = (HttpServletRequest) pageContext.getRequest();

        StringBuffer initCode = new StringBuffer();

        String contextPath = request.getContextPath();
        if ("/".equals(contextPath) || contextPath == null) {
            contextPath = "";
        }
        String src = contextPath + "/TinyMCE/tiny_mce.js";
        
        initCode.append("<script language=\"javascript\" type=\"text/javascript\" ");
        initCode.append("src=\"").append(src).append("\"></script>");
        initCode.append("<script language=\"javascript\" type=\"text/javascript\">");
		initCode.append("tinyMCE.init({");
		initCode.append("theme : \"advanced\"");
		initCode.append(", mode  : \"textareas\"");
		initCode.append(", editor_selector : \"contentEditorInstance\"");
		initCode.append(", dialog_type : \"window\"");
		initCode.append(", remove_linebreaks : false");
		initCode.append(", language : \"").append(defaultLanguage).append("\"");
        initCode.append(", docs_language : \"").append(defaultLanguage).append("\"");
		initCode.append(", content_css : \"").append(editorAreaCss.trim()).append("\"");
		initCode.append(", plugins : \"safari,table,save,advhr,advimage,advlink,emotions,iespell,preview,searchreplace,print,contextmenu,paste,directionality,fullscreen\"");
		initCode.append(", theme_advanced_buttons1_add_before : \"save,separator\"");
		initCode.append(", theme_advanced_buttons1_add : \"fontselect,fontsizeselect\"");
		initCode.append(", theme_advanced_buttons2_add : \"separator,preview,separator,forecolor,backcolor\"");
		initCode.append(", theme_advanced_buttons2_add_before: \"cut,copy,paste,pastetext,pasteword,separator,search,replace,separator\"");
		initCode.append(", theme_advanced_buttons3_add_before : \"tablecontrols,separator\"");
		initCode.append(", theme_advanced_buttons3_add : \"emotions,iespell,advhr,separator,print,separator,ltr,rtl,separator,fullscreen\"");
		initCode.append(", theme_advanced_toolbar_location : \"top\"");
		initCode.append(", theme_advanced_toolbar_align : \"left\"");
		initCode.append(", theme_advanced_path_location : \"bottom\"");
		initCode.append(", extended_valid_elements : \"a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]\"");
		initCode.append(", file_browser_callback : \"tinyMCEBrowserCallBack\"");
		initCode.append(", init_instance_callback : \"tinyMCEInitInstanceCallBack\"");
		if ( !GenericValidator.isBlankOrNull(baseHref) ) {
			initCode.append(", relative_urls : true");
			initCode.append(", document_base_url : \"").append(baseHref).append("\"");
		}
        initCode.append(", apply_source_formatting : true");
		initCode.append("});");

		initCode.append("this.editorAreaLanguages = new Array();");

		initCode.append("</script>");

		return initCode;
	}
}
